#include "lcd.h"
#include "ASCII.h"
#include "GB1616.h"	//16*16汉字字模
#include "gpio.h"  
#include <unistd.h>

 void LCD_GPIO_Config(void)
{
    GPIO_Init();
    //data
    GPIO_ConfigPin(D0_Port,D0_PIN,OUT);
    GPIO_ConfigPin(D1_Port,D1_PIN,OUT);
    GPIO_ConfigPin(D2_Port,D2_PIN,OUT);
    GPIO_ConfigPin(D3_Port,D3_PIN,OUT);
    GPIO_ConfigPin(D4_Port,D3_PIN,OUT);
    GPIO_ConfigPin(D5_Port,D4_PIN,OUT);
    GPIO_ConfigPin(D6_Port,D5_PIN,OUT);
    GPIO_ConfigPin(D7_Port,D6_PIN,OUT);
    GPIO_ConfigPin(D8_Port,D7_PIN,OUT);
    GPIO_ConfigPin(D9_Port,D8_PIN,OUT);
    GPIO_ConfigPin(D10_Port,D10_PIN,OUT);
    GPIO_ConfigPin(D11_Port,D11_PIN,OUT);
    GPIO_ConfigPin(D12_Port,D12_PIN,OUT);
    GPIO_ConfigPin(D13_Port,D13_PIN,OUT);
    GPIO_ConfigPin(D14_Port,D14_PIN,OUT);
    GPIO_ConfigPin(D15_Port,D15_PIN,OUT);

    GPIO_ConfigPin(RD_Port,RD_PIN,OUT);
    GPIO_ConfigPin(RS_Port,RS_PIN,OUT);
    GPIO_ConfigPin(WR_Port,WR_PIN,OUT);
    GPIO_ConfigPin(CS_Port,CS_PIN,OUT);
    GPIO_ConfigPin(BL_Port,BL_PIN,OUT);
    GPIO_ConfigPin(RST_Port,RST_PIN,OUT);
 
    GPIO_SetBits(RD_Port,RD_PIN);
	
}

static SendData(unsigned int data)
{
    REGS Fictitious_REG;
    
    REGDATA=data;

    GPIO_Bit(D0_Port,D0_PIN,regbit0);
    GPIO_Bit(D1_Port,D1_PIN,regbit1);
    GPIO_Bit(D2_Port,D2_PIN,regbit2);
    GPIO_Bit(D3_Port,D3_PIN,regbit3);
    GPIO_Bit(D4_Port,D3_PIN,regbit4);
    GPIO_Bit(D5_Port,D4_PIN,regbit5);
    GPIO_Bit(D6_Port,D5_PIN,regbit6);
    GPIO_Bit(D7_Port,D6_PIN,regbit7);
    GPIO_Bit(D8_Port,D7_PIN,regbit8);
    GPIO_Bit(D9_Port,D8_PIN,regbit9);
    GPIO_Bit(D10_Port,D10_PIN,regbit10);
    GPIO_Bit(D11_Port,D11_PIN,regbit11);
    GPIO_Bit(D12_Port,D12_PIN,regbit12);
    GPIO_Bit(D13_Port,D13_PIN,regbit13);
    GPIO_Bit(D14_Port,D14_PIN,regbit14);
    GPIO_Bit(D15_Port,D15_PIN,regbit15);

}

static void LCD_Reset(void)//液晶屏复位函数（通常触摸屏与液晶屏共用复位）
{
	Clr_Rst;
	LCD_delay(1000);					   
	Set_Rst;		 	 
	LCD_delay(1000);
}
void LCD_delay(int time)  //简单软件 延时函数
{
	unsigned short i;

    for(i=0;i<time;i++)
    {
        usleep(1000);
    }

}

void WriteComm(unsigned char CMD) //写命令
{
    unsigned int command;
    command = (unsigned int)CMD;
    
	LCD_RS(0);//RS=0 表示写入的是命令，51单片机写法：P2_0=0;
	SendData(command);  //写入8位命令，51单片机写法：P1=CMD;
	//**** WR一个高低电平实现写入 ******//
	LCD_WR(0);//WR=0，51单片机写法：P2_1=0;
	LCD_WR(1);//WR=1，51单片机写法：P2_1=1;
}

void WriteData(u32 dat) //写数据
{
    unsigned int command;
    command = (unsigned int)dat;
	LCD_RS(1);//RS=1 表示写入的是数据，51单片机写法：P2_0=1;
	SendData(command);    //写入8位数据，51单片机写法：P1=dat;
	// WR一个高低电平实现写入 
	LCD_WR(0);//WR=0，51单片机写法：P2_1=0;
	LCD_WR(1);//WR=1，51单片机写法：P2_1=1;
}
/******************************************
函数名：  Lcd写命令函数
功能：    向Lcd指定位置写入应有命令或数据
入口参数：Index 要寻址的寄存器地址
          ConfigTemp 写入的数据或命令值
******************************************/
void LCD_WR_REG(u16 Index,u16 CongfigTemp)
{
	WriteComm(Index);   
	WriteData(CongfigTemp);
}
/**********************************************
函数名：开窗函数

入口参数：XStart x方向的起点
          Xend   x方向的终点
					YStart y方向的起点
          Yend   y方向的终点

这个函数的意义是：开一个矩形框，方便接下来往这个框填充数据
***********************************************/
void BlockWrite(unsigned int Xstart,unsigned int Xend,unsigned int Ystart,unsigned int Yend) 
{
	WriteComm(0x2a);
	WriteData(Xstart>>8);
	WriteData(Xstart);
	WriteData(Xend>>8);
	WriteData(Xend);

	WriteComm(0x2b);   
	WriteData(Ystart>>8);
	WriteData(Ystart);
	WriteData(Yend>>8);
	WriteData(Yend);
	
	WriteComm(0x2c);

}
/**********************************************
函数名：Lcd矩形填充函数

入口参数：xStart x方向的起始点
          ySrart y方向的终止点
          xLong 要选定矩形的x方向长度
          yLong  要选定矩形的y方向长度
返回值：无
***********************************************/
void Lcd_ColorBox(u16 xStart,u16 yStart,u16 xLong,u16 yLong,u32 Color)
{
		u32 temp;

	BlockWrite(xStart,xStart+xLong-1,yStart,yStart+yLong-1);
	LCD_RS(1);//RS=1
	
	for (temp=0; temp<xLong*yLong; temp++)
	{
		SendData(Color);   //写入颜色低8位，51单片机写法：P1=Color;
		LCD_WR(0);//WR=0，51单片机写法：P2_1=0;
		LCD_WR(1);//WR=1，51单片机写法：P2_1=1;
	}
}
void LCD_Initial(void) //LCD初始化函数
{
LCD_GPIO_Config();  //初始化液晶屏相关GPIO
LCD_Reset();		//复位液晶屏
Lcd_Light_ON;       //PD8为高电平 背光打开
LCD_CS(0);          // CS = 0,使能LCD
	
//************* Start Initial Sequence **********// 
WriteComm(0x11);                           //Exit Sleep 
LCD_delay(50);
WriteComm(0xFF);                               // EXTC Command Set enable register 
WriteData(0xFF); 
WriteData(0x98); 
WriteData(0x26); 
 
WriteComm(0xBC);                               // GIP 1 
WriteData(0x21); 
WriteData(0x06); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0x01); 
WriteData(0x01); 
WriteData(0x80); 
WriteData(0x02); 
WriteData(0x05); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0x01); 
WriteData(0x01); 
WriteData(0xF0); 
WriteData(0xF4); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0xC0);  
 
WriteData(0x08); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0x00); 
 
WriteComm(0xBD);                               // GIP 2 
WriteData(0x02); 
WriteData(0x13); 
WriteData(0x45); 
WriteData(0x67); 
WriteData(0x01); 
WriteData(0x23); 
WriteData(0x45); 
WriteData(0x67); 
 
WriteComm(0xBE);                               // GIP 3 
WriteData(0x13); 
WriteData(0x22); 
WriteData(0x22); 
WriteData(0x22); 
WriteData(0x22); 
WriteData(0xBB); 
WriteData(0xAA); 
WriteData(0xDD); 
WriteData(0xCC); 
WriteData(0x66); 
WriteData(0x77); 
WriteData(0x22); 
WriteData(0x22); 
WriteData(0x22); 
WriteData(0x22); 
WriteData(0x22); 
WriteData(0x22); 
 
WriteComm(0x3A);                               // Pixel Format 
WriteData(0x66); 
 
WriteComm(0xFA);                               // P5_ bit 3 =1    Turn off VRGH 
WriteData(0x08); 
WriteData(0x00); 
WriteData(0x00); 
WriteData(0x02); 
WriteData(0x08); 
 
WriteComm(0xB1);                               // FRAME RATE Setting 
WriteData(0x00); 
WriteData(0x58); 
WriteData(0x03); 
 
WriteComm(0XB4);                               // Inversion Type 
WriteData(0x02);

WriteComm(0XC0);                               // Power Control 1 
WriteData(0x8A); 
 
WriteComm(0XC1);                               // Power Control 2 
WriteData(0x10); 
WriteData(0x78); 
WriteData(0x6A); 
 
WriteComm(0xC7);                               // VCOM Control 
WriteData(0x5D); //5D
//WriteData(0x0); 
//WriteData(0x0); 
//WriteData(0x0); 
 
WriteComm(0xED);                               // EN_volt_reg 
WriteData(0x7F); 
WriteData(0x0F); 
 
WriteComm(0xF2);                                // Engineering Setting 
WriteData(0x02); 
WriteData(0x07); 
WriteData(0x03); 
WriteData(0x92); 
WriteData(0x07); 
WriteData(0x04); 
 
WriteComm(0xF7);                                // Resolution Control 
WriteData(0x02); 
 
WriteComm(0xE0);  
 
WriteData(0x00);     //P1 
WriteData(0x05);     //P2 
WriteData(0x0E);     //P3 
WriteData(0x0E);     //P4 
WriteData(0x11);     //P5 
WriteData(0x19);     //P6 
WriteData(0xCB);    //P7 
WriteData(0x09);     //P8 
WriteData(0x02);     //P9 
WriteData(0x07);     //P10 
WriteData(0x04);     //P11 
WriteData(0x10);     //P12 
WriteData(0x0D);    //P13 
WriteData(0x32);     //P14 
WriteData(0x2C);    //P15 
WriteData(0x00);     //P16 
 
WriteComm(0xE1); 
WriteData(0x00);     //P1 
WriteData(0x04);     //P2 
WriteData(0x09);     //P3 
WriteData(0x0E);     //P4 
WriteData(0x10);     //P5 
WriteData(0x15);     //P6 
WriteData(0x79);     //P7 
WriteData(0x07);     //P8 
WriteData(0x05);     //P9 
WriteData(0x09);     //P10 
WriteData(0x06);     //P11 
WriteData(0x0E);     //P12 
WriteData(0x0C);    //P13 
WriteData(0x28);     //P14 
WriteData(0x22);     //P15 
WriteData(0x00);     //P16 
 
WriteComm(0x35);                                //Tearing Effect ON 
WriteData(0x00); 
 
LCD_delay(50); 
WriteComm(0x29);                                // Display On 
LCD_delay(10); 

WriteComm(0x3A);  
WriteData(0x55); 
WriteComm(0x36);  
WriteData(0xA0); 

}
/******************************************
函数名：Lcd图像填充
功能：向Lcd指定位置填充图像
入口参数：
					(x,y): 图片左上角起始坐标
					(pic_H,pic_V): 图片的宽高
					 pic  指向存储图片数组的指针
******************************************/
void LCD_Fill_Pic(u16 x, u16 y,u16 pic_H, u16 pic_V, const unsigned int*  pic)
{
	//DMA 方式
//	BlockWrite(x,x+pic_H-1,y,y+pic_V-1);
//	TK80_DMA_Init((u32)pic,pic_H*pic_V);//DMA初始化
//	while((DMA2->ISR & 0x20)==0);
//	DMA2->IFCR |=1<<5;
	
	//========= 轮询方式=========//
  unsigned long i;
	unsigned long j;
	BlockWrite(x,x+pic_H-1,y,y+pic_V-1);
	j= pic_H*pic_V;
	LCD_RS(1);//RS=1 表示写入的是数据，51单片机写法：P2_0=1;
	for (i = 0; i <j; i++)  
	{
		SendData(pic[i]); //写入颜色，51单片机写法：P1=pic[i];
		LCD_WR(0);//WR=0，51单片机写法：P2_1=0;
		LCD_WR(1);//WR=1，51单片机写法：P2_1=1;
	}
}
//=============== 在x，y 坐标上打一个颜色为Color的点 ===============
void DrawPixel(u16 x, u16 y, int Color)
{
	BlockWrite(x,x,y,y); 
  LCD_RS(1);//RS=1 表示写入的是数据，51单片机写法：P2_0=1;
	SendData(Color);    //写入颜色低8位，51单片机写法：P1=Color;
	LCD_WR(0);//WR=0，51单片机写法：P2_1=0;
	LCD_WR(1);//WR=1，51单片机写法：P2_1=1;
}

/**********8*16字体 ASCII码 显示*************
(x,y): 显示字母的起始坐标
num:   要显示的字符:" "--->"~"
fColor 前景色
bColor 背景色
flag:  有背景色(1)无背景色(0)
*********************************************/
void SPILCD_ShowChar(unsigned short x,unsigned short y,unsigned char num, unsigned int fColor, unsigned int bColor,unsigned char flag) 
{       
	unsigned char temp;
	unsigned int pos,i,j;  

	num=num-' ';//得到偏移后的值
	i=num*16; 	
	BlockWrite(x,x+7,y,y+15);
	for(pos=0;pos<16;pos++)
		{
			temp=nAsciiDot[i+pos];	//调通调用ASCII字体
			for(j=0;j<8;j++)
		   {                 
		        if(temp&0x80)
							WriteData(fColor);
						else 
							WriteData(bColor);
							temp<<=1; 
		    }
		}		 
}  

/**********写一个16x16的汉字*****************
(x,y): 显示汉字的起始坐标
c[2]:  要显示的汉字
fColor 前景色
bColor 背景色
flag:  有背景色(1)无背景色(0)
*********************************************/
void PutGB1616(unsigned short x, unsigned short  y, unsigned char c[2], unsigned int fColor,unsigned int bColor,unsigned char flag)
{
	unsigned int i,j,k;
	unsigned char m;

	BlockWrite(x,x+15,y,y+15);

	for (k=0;k<64;k++) { //64标示自建汉字库中的个数，循环查询内码
	  if ((codeGB_16[k].Index[0]==c[0])&&(codeGB_16[k].Index[1]==c[1]))
			{ 
    	for(i=0;i<32;i++) 
			{
				m=codeGB_16[k].Msk[i];
				for(j=0;j<8;j++) 
				{		
					if((m&0x80)==0x80) {
						WriteData(fColor);
						}
					else {
						WriteData(bColor);
						}
					m=m<<1;
				} 
		  }
		}  
	  }	
	}
/**********显示一串字*****************
(x,y): 字符串的起始坐标
*s:    要显示的字符串指针
fColor 前景色
bColor 背景色
flag:  有背景色(1)无背景色(0)
*********************************************/
void LCD_PutString(unsigned short x, unsigned short y, char *s, unsigned int fColor, unsigned int bColor,unsigned char flag) 
	{
		unsigned char l=0;
		while(*s) 
			{
				if( *s < 0x80) 
						{
							SPILCD_ShowChar(x+l*8,y,*s,fColor,bColor,flag);
							s++;l++;
						}
				else
						{
							PutGB1616(x+l*8,y,(unsigned char*)s,fColor,bColor,flag);
							s+=2;l+=2;
						}
			}
	}
